home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
OS2
/
MS_SH200.ARJ
/
DIRECTOR.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-11-25
|
6KB
|
304 lines
/*
* @(#)msd_dir.c 1.4 87/11/06 Public Domain.
*
* A public domain implementation of BSD directory routines for
* MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
* August 1897
*
* Modified by Ian Stewartson, Data Logic.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <dirent.h>
#ifdef OS2
#define INCL_DOSFILEMGR
#include <os2.h>
#else
#include <dos.h>
#endif
#ifdef OS2
# define ATTRIBUTES (FILE_DIRECTORY | FILE_HIDDEN | FILE_SYSTEM | \
FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED)
#else
# define ATTRIBUTES (_A_SUBDIR | _A_HIDDEN | _A_SYSTEM | \
_A_NORMAL | _A_RDONLY | _A_ARCH)
#endif
typedef struct _dircontents DIRCONT;
static void free_dircontents (DIRCONT *);
DIR *opendir (name)
const char *name;
{
struct stat statb;
DIR *dirp;
char *last;
DIRCONT *dp;
char *nbuf;
#ifdef OS2
FILEFINDBUF dtabuf;
HDIR d_handle = HDIR_SYSTEM;
USHORT d_count = 1;
bool HPFS = FALSE;
#else
struct find_t dtabuf;
#endif
int len = strlen (name);
if (!len)
{
errno = ENOTDIR;
return (DIR *)NULL;
}
if ((nbuf = malloc (len + 5)) == (char *)NULL)
return (DIR *) NULL;
strcpy (nbuf, name);
last = &nbuf[len - 1];
/* Ok, DOS is very picky about its directory names. The following are
* valid.
*
* c:/
* c:.
* c:name/name1
*
* c:name/ is not valid
*/
if (((*last == '\\') || (*last == '/')) && (len > 1) &&
(!((len == 3) && (name[1] == ':'))))
*(last--) = 0;
/* Check its a directory */
if (stat (nbuf, &statb) < 0)
{
free (nbuf);
return (DIR *) NULL;
}
if (!S_ISDIR (statb.st_mode))
{
free (nbuf);
errno = ENOTDIR;
return (DIR *)NULL;
}
if ((dirp = (DIR *) malloc (sizeof (DIR))) == (DIR *) NULL)
{
free (nbuf);
return (DIR *) NULL;
}
/* Set up to find everything */
if ((*last != '\\') && (*last != '/'))
strcat (last, "/");
strcat (last, "*.*");
/* For OS/2, find the file system type */
#ifdef OS2
HPFS = IsHPFSFileSystem (nbuf);
#endif
dirp->dd_loc = 0;
dirp->dd_cp = (DIRCONT *) NULL;
dirp->dd_contents = (DIRCONT *) NULL;
#ifdef OS2
if (DosFindFirst (nbuf, &d_handle, ATTRIBUTES, &dtabuf,
sizeof (FILEFINDBUF), &d_count, (ULONG)0) != 0)
#else
if (_dos_findfirst (nbuf, ATTRIBUTES, &dtabuf) != 0)
#endif
{
free (nbuf);
return dirp;
}
do
{
#ifdef OS2
if (((dp = (DIRCONT *) malloc (sizeof (DIRCONT))) == (DIRCONT *)NULL) ||
((dp->_d_entry = strdup (dtabuf.achName)) == (char *) NULL))
#else
if (((dp = (DIRCONT *) malloc (sizeof (DIRCONT))) == (DIRCONT *)NULL) ||
((dp->_d_entry = strdup (dtabuf.name)) == (char *) NULL))
#endif
{
if (dp != (char *)NULL)
free ((char *)dp);
free (nbuf);
free_dircontents (dirp->dd_contents);
#ifdef OS2
DosFindClose (d_handle);
#endif
return (DIR *) NULL;
}
#ifdef OS2
if (!HPFS)
strlwr (dp->_d_entry);
#endif
if (dirp->dd_contents != (DIRCONT *) NULL)
dirp->dd_cp = dirp->dd_cp->_d_next = dp;
else
dirp->dd_contents = dirp->dd_cp = dp;
dp->_d_next = (DIRCONT *) NULL;
#ifdef OS2
d_count = 1;
} while (DosFindNext (d_handle, &dtabuf, sizeof (FILEFINDBUF),
&d_count) == 0);
#else
} while (_dos_findnext (&dtabuf) == 0);
#endif
dirp->dd_cp = dirp->dd_contents;
free (nbuf);
#ifdef OS2
DosFindClose (d_handle);
#endif
return dirp;
}
int closedir (dirp)
DIR *dirp;
{
free_dircontents (dirp->dd_contents);
free ((char *)dirp);
return 0;
}
struct dirent *readdir (dirp)
DIR *dirp;
{
static struct dirent dp;
if (dirp->dd_cp == (DIRCONT *) NULL)
return (struct dirent *) NULL;
dp.d_reclen = strlen (strcpy (dp.d_name, dirp->dd_cp->_d_entry));
dp.d_off = dirp->dd_loc * 32;
dp.d_ino = (ino_t)++dirp->dd_loc;
dirp->dd_cp = dirp->dd_cp->_d_next;
#ifndef OS2
strlwr (dp.d_name);
#endif
return &dp;
}
void rewinddir (dirp)
DIR *dirp;
{
seekdir (dirp, (off_t)0);
}
void seekdir (dirp, off)
DIR *dirp;
off_t off;
{
long i = off;
DIRCONT *dp;
if (off < 0L)
return;
for (dp = dirp->dd_contents; (--i >= 0) && (dp != (DIRCONT *)NULL);
dp = dp->_d_next)
;
dirp->dd_loc = off - (i + 1);
dirp->dd_cp = dp;
}
off_t telldir(dirp)
DIR *dirp;
{
return dirp->dd_loc;
}
static void free_dircontents (dp)
DIRCONT *dp;
{
DIRCONT *odp;
while ((odp = dp) != (DIRCONT *)NULL)
{
if (dp->_d_entry != (char *)NULL)
free (dp->_d_entry);
dp = dp->_d_next;
free ((char *)odp);
}
}
/*
* For OS/2, we need to know if we have to convert to lower case. This
* only applies to non-HPFS (FAT, NETWARE etc) file systems.
*/
#ifdef OS2
bool IsHPFSFileSystem (char *directory)
{
USHORT nDrive;
ULONG lMap;
BYTE bData[64];
BYTE bName[3];
USHORT cbData;
if ( _osmode == DOS_MODE )
return FALSE;
/*
* Mike tells me there are IFS calls to determine this, but he carn't
* remember which. So we read the partition info and check for HPFS.
*/
if (isalpha (directory[0]) && (directory[1] == ':'))
nDrive = toupper (directory[0]) - '@';
else
DosQCurDisk (&nDrive, &lMap);
/* Set up the drive name */
bName[0] = (char) (nDrive + '@');
bName[1] = ':';
bName[2] = 0;
cbData = sizeof (bData);
/* Read the info, if we fail - assume non-HPFS */
if (DosQFSAttach (bName, 0, FSAIL_QUERYNAME, bData, &cbData, 0L) )
return FALSE;
else if (!strcmp (bData + (*((USHORT *) (bData + 2)) + 7), "HPFS"))
return TRUE;
else
return FALSE;
}
#endif